package yawning.mew.cat;

import yawning.mew.ProcEffect.Trigger;
import yawning.mew.cat.CatModelSimState.CatTargetData;
import yawning.mew.cat.CatModelSimulation.SimulatorProperty;
import yawning.mew.character.CharacterModel.AttackResult;
import yawning.mew.sim.SimulationAction;
import yawning.mew.sim.SimulationEventAction;
import yawning.mew.sim.SimulationTarget;

public class EventMangleDebuff extends SimulationEventAction {
	CatModelSimState mState;
	private SimulationTarget mTarget;
	private String mTargetName;
	private CatTargetData mTargetData;
	private boolean mExternalDebuff;


	EventMangleDebuff(CatModelSimState state, CatTargetData targetData) {
		super(state.mSimEngine);
		mState = state;
		mTarget = targetData.getSimulationTarget();
		mTargetData = targetData;
		mTargetName = targetData.getSimulationTarget().getTarget().getName();
		mExternalDebuff = mState.mSimEngine.getConfig().getBool(SimulatorProperty.ASSUMEEXTERNALMANGLE);
		if (mExternalDebuff) {
			if (mState.mIsLogging) mState.mLog.log("Mangle: %s External\n", mTargetName);

			schedule(Double.MAX_VALUE);
		}
	}

	@Override
	public double perform() {
		int cost = mState.getEnergyCost(mState.mModel.mangleCost);
		if (mState.getEnergy() < cost && !mState.mOocEv.isUp()) return SimulationAction.ACTION_FAIL;
		int prevEnergy = mState.getEnergy(); int prevCps = mState.getComboPoints();

		AttackResult result = (mTargetData.mCanParry) ? mState.mModel.getFrontalYellowResult() : mState.mModel.getYellowResult();

		if (result == AttackResult.MISS) {
			cost = (int) Math.round(cost * 0.2);
			mNrMangleMiss++;

			if (mState.mIsLogging) mState.mLog.log("Mangle: %s MISS\n", mTargetName);
		} else if (result == AttackResult.DODGE) {
			cost = (int) Math.round(cost * 0.2);
			mNrMangleDodge++;

			if (mState.mIsLogging) mState.mLog.log("Mangle: %s DODGE\n", mTargetName);
		} else if (result == AttackResult.PARRY) {
			cost = (int) Math.round(cost * 0.2);
			mNrMangleParry++;

			if (mState.mIsLogging) mState.mLog.log("Mangle: %s PARRY\n", mTargetName);
		} else {
			double damage = mState.mModel.getWeaponDamage() * mState.mModel.levelDep.getMangleMult() + mState.mModel.levelDep.getMangleDmg();

			damage *= mState.mModel.multMangleGlyph;

			if (result == AttackResult.CRIT) {
				mNrMangleCrit++;
				damage *= mState.mModel.multCrit;
			} else {
				mNrMangleHit++;
			}

			damage *= mState.getDirectDamageMult();
			mMangleDamage += Math.round(damage);

			if (mState.mIsLogging) mState.mLog.log("Mangle: %s %s Damage: %d", mTargetName, result, Math.round(damage));

			if (!mExternalDebuff) schedule(mState.mModel.mangleDebuffDuration);

			if (mState.mModel.druid.tier_11_4pc) {
				mState.mTier_11_4pcEv.run();
				if (mState.mIsLogging) mState.mLog.logAppend("\n  Tier 11 4pc Stacks: %d (%.3f)", Math.round(mState.mModel.tier_11_4pc_buffStacks), mState.mTier_11_4pcEv.getExpiryTime());
			}

			if (mState.mIsLogging) mState.mLog.logAppend("\n");

			if (result == AttackResult.CRIT) mState.mSimEngine.triggerProc(mTarget, Trigger.YELLOWCRIT); else mState.mSimEngine.triggerProc(mTarget, Trigger.YELLOW);

			// Handle Glyph of Bloodletting.
			if (mTargetData.mRipAction.isUp() && mState.mModel.ripGlyphExtDuration > 0) mTargetData.mRipAction.onGlyphTrigger();

			if (mState.mModel.druid.tier_12_2pc) mTargetData.mTier_12_2pcEv.run(damage);

			mState.onCpGenerator(result == AttackResult.CRIT);
		}

		if (mState.mOocEv.isUp()) mNrMangleOoC++;
		if (mState.mTigersFuryEv.isUp()) mNrMangleTF++;

		mMangleEnergy += mState.onOoCConsumer(cost);

		mState.logResourceChange(prevEnergy, prevCps);

		return 1.0;
	}

	@Override
	public void onExpire() {
		if (mState.mIsLogging) mState.mLog.log("Mangle: %s Expiration\n", mTargetName);
	}

	long mMangleDamage = 0;
	int mNrMangleMiss = 0;
	int mNrMangleDodge = 0;
	int mNrMangleParry = 0;
	int mNrMangleCrit = 0;
	int mNrMangleHit = 0;

	int mMangleEnergy;
	int mNrMangleOoC;
	int mNrMangleTF;
}
